package com.person.yhzs.wxPayV3.util;

import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * @author luolin
 * @Description 支付工具类
 * @createTime 2022年06月24日 11:08:00
 */
public class WXPayV3Util {

    static private final Logger LOGGER = LoggerFactory.getLogger(WXPayV3Util.class);

    /**
     * 请求时设置签名   组件
     * @param components the components
     * @return string string
     */
    private static String createSign(boolean newLine, String... components) {
        String suffix = newLine ? "\n" : "";
        return Arrays.stream(components).collect(Collectors.joining("\n", "", suffix));
    }

    /**
     *
     * @param privateKey
     * @param orderedComponents
     * @return
     */
    public static String doRequestSign(String privateKey, String... orderedComponents) {
        try {
            // 商户私钥
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
            Signature signer = Signature.getInstance("SHA256withRSA");
            signer.initSign(merchantPrivateKey);
            final String signatureStr = createSign(true, orderedComponents);
            signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
            return Base64Utils.encodeToString(signer.sign());
        } catch (InvalidKeyException e) {
            LOGGER.error("InvalidKeyException: {}", e);
        } catch (SignatureException e) {
            LOGGER.error("SignatureException: {}", e);
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("NoSuchAlgorithmException: {}", e);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("UnsupportedEncodingException: {}", e);
        }
        return null;
    }


    /**
     * 使用微信平台证书，对微信回调数据验签，做应答签名比较
     * @param certificate
     * @param wechatpaySignature
     * @param wechatpayTimestamp
     * @param wechatpayNonce
     * @param body
     * @return
     */
    public static boolean responseSignVerify(String certificate, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String body) {
        try {
            final String signatureStr = createSign(true, wechatpayTimestamp, wechatpayNonce, body);
            Signature signer = Signature.getInstance("SHA256withRSA");
            signer.initVerify(PemUtil.loadCertificate(new ByteArrayInputStream(certificate.getBytes("utf-8"))));
            signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
            // ...
            return signer.verify(Base64Utils.decodeFromString(wechatpaySignature));
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("UnsupportedEncodingException: {}", e);
        } catch (SignatureException e) {
            LOGGER.error("SignatureException: {}", e);
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("NoSuchAlgorithmException: {}", e);
        } catch (InvalidKeyException e) {
            LOGGER.error("InvalidKeyException: {}", e);
        }
        return false;
    }

    /**
     * 字符串
     * @return
     */
    public static String CreateNoncestr() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < 16; i++) {
            Random rd = new Random();
            res += chars.charAt(rd.nextInt(chars.length() - 1));
        }
        return res;
    }

    /**
     * 得到时间戳
     * @return
     */
    public static String getTimestamp() {
        long epochSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        return String.valueOf(epochSecond);
//		return Long.toString(System.currentTimeMillis() / 1000);
    }
}
